package com.hgq.jssjyyxt.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hgq.jssjyyxt.constant.RedisConstant;
import com.hgq.jssjyyxt.entity.Trainers;
import com.hgq.jssjyyxt.entity.Users;
import com.hgq.jssjyyxt.enums.RoleEnum;
import com.hgq.jssjyyxt.enums.StateEnum;
import com.hgq.jssjyyxt.service.TrainersService;
import com.hgq.jssjyyxt.util.DateUtil;
import com.hgq.jssjyyxt.util.OrderGenerator;
import com.hgq.jssjyyxt.util.Result;

import com.hgq.jssjyyxt.util.ValidToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.MailSendException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * (Trainers)表控制层
 *
 * @author makejava
 * @since 2024-04-11 13:53:46
 */
@Slf4j
@Transactional(rollbackFor = Exception.class)
@RestController
@RequestMapping("trainers")
public class TrainersController {
    /**
     * 服务对象
     */
    @Resource
    private TrainersService trainersService;
    @Resource
    RedisTemplate<String, Integer> redisTemplate;
    @Resource
    private JavaMailSender mailSender;

    @Value("${send-email}")
    private String email;


    /**
     * 分页查询
     *
     * @param trainers 筛选条件
     * @param limit    分页对象
     * @param page     分页对象
     * @return 查询结果
     */
    @GetMapping("findAll")
    public Result findAll(Trainers trainers, Integer limit, Integer page) {
        if (limit == null || page == null) {
            return Result.failure("limit和page不能为空");
        }
        return trainersService.selectAll(trainers, limit, page);
    }

    //查询所有教练信息
    @GetMapping("findAllTrainers")
    public Result findAllTrainers() {
        QueryWrapper<Trainers> trainersQueryWrapper = new QueryWrapper<>();
        trainersQueryWrapper.eq("state", StateEnum.PASSED.getCode());
        trainersQueryWrapper.eq("role", RoleEnum.COACH.getCode());
        return Result.success(trainersService.list(trainersQueryWrapper));
    }


    /**
     * 通过主键查询单条数据
     *
     * @param request 请求
     * @return 单条数据
     */
    @GetMapping("getById")
    public Result getById(HttpServletRequest request) {
        Integer id = ValidToken.getIdByToken(request, redisTemplate);
        Trainers byId = trainersService.getById(id);
        return Result.success(byId);
    }

    /**
     * 新增数据
     *
     * @param trainers 实体
     * @return 新增结果
     */
    @PostMapping("add")
    public Result add(@RequestBody Trainers trainers) {
        //判断是否为空
        if (trainers == null) {
            return Result.failure("参数不能为空");
        }

        //如果头像为空，则填充默认头像
        String avatar = trainers.getAvatar();
        if (!StringUtils.hasLength(avatar)) {
            trainers.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        }

        //判断账号是否已经存在
        if (this.trainersService.count(new QueryWrapper<Trainers>().eq("account", trainers.getAccount())) > 0) {
            return Result.failure("账号已存在");
        }

        //填充默认密码
        trainers.setPassword("123456");
        trainers.setAccountBalance(BigDecimal.ZERO);
        trainers.setFreezeMoney(BigDecimal.ZERO);
        if (this.trainersService.save(trainers)) {
            return Result.success("添加成功");
        }
        return Result.failure("添加失败");
    }

    /**
     * 编辑数据
     *
     * @param trainers 实体
     * @return 编辑结果
     */
    @PostMapping("edit")
    public Result edit(@RequestBody Trainers trainers) {
        //判断是否为空
        if (trainers == null) {
            return Result.failure("参数不能为空");
        }

        if (this.trainersService.updateById(trainers)) {
            return Result.success("修改成功");
        }
        return Result.failure("修改失败");
    }

    /**
     * 同意教练
     *
     * @param trainers 实体
     * @return 编辑结果
     */
    @PostMapping("pass")
    public Result pass(@RequestBody Trainers trainers) throws MessagingException, UnsupportedEncodingException {
        //判断是否为空
        if (trainers == null) {
            return Result.failure("参数不能为空");
        }

        Trainers byId = trainersService.getById(trainers.getTrainerId());

        if (!sendSimpleMails(byId.getEmail(), "健身系统", true, "")) {
            return Result.failure("发送失败，请查看邮箱是否正确.");
        }

        if (this.trainersService.updateById(trainers)) {
            return Result.success("同意成功");
        }
        return Result.failure("同意失败");
    }

    /**
     * 拒绝教练
     *
     * @param trainers 实体
     * @return 编辑结果
     */
    @PostMapping("reject")
    public Result reject(@RequestBody Trainers trainers) throws MessagingException, UnsupportedEncodingException {
        //判断是否为空
        if (trainers == null) {
            return Result.failure("参数不能为空");
        }
        Trainers byId = trainersService.getById(trainers.getTrainerId());
        if (!sendSimpleMails(byId.getEmail(), "健身系统", false, trainers.getMsg())) {
            return Result.failure("发送失败，请查看邮箱是否正确.");
        }

        if (this.trainersService.updateById(trainers)) {
            return Result.success("拒绝成功");
        }
        return Result.failure("拒绝失败");
    }

    /**
     * 删除数据
     *
     * @param data 主键
     * @return 删除是否成功
     */
    @PostMapping("delete")
    public Result deleteById(@RequestBody JSONObject data) {
        //判断id是否为空
        Integer id = data.getInteger("categoryId");
        if (id == null) {
            return Result.failure("id不能为空");
        }

        if (this.trainersService.removeById(id)) {
            return Result.success("删除成功");
        }
        return Result.failure("删除失败");
    }

    @PostMapping("login")
    public Result login(@RequestBody Trainers trainers) {
        //判断是否为空
        if (trainers == null) {
            return Result.failure("参数不能为空");
        }

        //根据账号和角色进行查找
        QueryWrapper<Trainers> usersQueryWrapper = new QueryWrapper<>();
        usersQueryWrapper.eq("account", trainers.getAccount());
        Trainers one = trainersService.getOne(usersQueryWrapper);

        if (one == null) {
            return Result.failure("账号不存在,请先注册");
        }

        if (!one.getPassword().equals(trainers.getPassword())) {
            return Result.failure("密码错误,请重新输入");
        }

        if (RoleEnum.COACH.getCode().equals(one.getRole())) {
            //判断是否通过审核
            if (!StateEnum.PASSED.getCode().equals(one.getState())) {
                return Result.failure("身份认证待审核，请稍等审核完毕后才能登陆！！！");
            }
        }

        String token = String.valueOf(OrderGenerator.generateOrderNumber());
        redisTemplate.opsForValue().set(token, one.getTrainerId(), RedisConstant.REDIS_SAVE_DURATION_ONE_DAY, TimeUnit.DAYS);
        return Result.success("登录成功", token);
    }

    @PostMapping("register")
    public Result register(@RequestBody Trainers trainers) throws MessagingException, UnsupportedEncodingException {
        //判断是否为空
        if (trainers == null) {
            return Result.failure("参数不能为空");
        }
        trainers.setRole(RoleEnum.COACH.getCode());
        trainers.setLevel(StateEnum.PASSED.getCode());
        trainers.setState(StateEnum.WAIT.getCode());

        //根据账号进行查找
        QueryWrapper<Trainers> usersQueryWrapper = new QueryWrapper<>();
        usersQueryWrapper.eq("account", trainers.getAccount());
        Trainers one = trainersService.getOne(usersQueryWrapper);

        if (one != null) {
            return Result.failure("账号已存在,请重新输入");
        }

        if (!verifyEmail(trainers.getEmail(), "健身系统")) {
            return Result.failure("发送失败，请查看邮箱是否正确.");
        }
        trainers.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        trainers.setAccountBalance(BigDecimal.ZERO);
        trainers.setFreezeMoney(BigDecimal.ZERO);
        if (this.trainersService.save(trainers)) {
            return Result.success("注册成功");
        }
        return Result.failure("注册失败");
    }

    /**
     * @param to      收件人
     * @param subject 主题
     * @return
     * @throws MessagingException
     * @throws UnsupportedEncodingException
     */
    public boolean verifyEmail(String to, String subject) throws MessagingException, UnsupportedEncodingException {
        try {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
            //发件人  别名
            mimeMessageHelper.setFrom(email, "scj");
            //收信人
            mimeMessageHelper.setTo(to);
            //主题
            mimeMessageHelper.setSubject(subject);
            //文本
            mimeMessageHelper.setText("<!DOCTYPE html><html><head><meta charset='utf-8'><title></title></head><body>" +
                    "<table>" +
                    "<tr><th>欢迎注册健身私教预约系统</th></tr>" +
                    "<tr><td>教练您好，您正在注册健身私教预约系统，此次邮件校验您的邮箱是否正确，不用回复。</td></tr>" +
                    "<tr><td>您的资质已提交等待审核完毕会及时通过邮件通知您。</td></tr>" +
                    "<tr><td>现在时间：" + DateUtil.getTime() + "</td></tr>" +
                    "</table></body></html>", true);

            mailSender.send(mimeMessage);
            log.info("发送邮件成功：发件人：{},收件人：{},主题：{},时间：{}", email, to, subject, DateUtil.getTime());
        } catch (MailSendException e) {
            Set<String> tmpInvalidMails = getInvalidAddress(e);
            // 非无效收件人导致的异常，暂不处理
            if (tmpInvalidMails.isEmpty()) {
                log.error(e.getMessage());
            }
            log.info("发送邮件失败：发件人：{},收件人：{},主题：{},时间：{},错误：{},结束：{}", email, to, subject, DateUtil.getTime(), e.getMessage(), "结束");
            return false;
        }
        return true;
    }

    /**
     * @param to        收件人
     * @param subject   主题
     * @param isSuccess 是否通过
     * @return
     * @throws MessagingException
     * @throws UnsupportedEncodingException
     */
    public boolean sendSimpleMails(String to, String subject, boolean isSuccess, String msg) throws MessagingException, UnsupportedEncodingException {
        try {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
            //发件人  别名
            mimeMessageHelper.setFrom(email, "scj");
            //收信人
            mimeMessageHelper.setTo(to);
            //主题
            mimeMessageHelper.setSubject(subject);
            if (isSuccess) {
                //文本
                mimeMessageHelper.setText("<!DOCTYPE html><html><head><meta charset='utf-8'><title></title></head><body>" +
                        "<table>" +
                        "<tr><th>欢迎注册健身私教预约系统</th></tr>" +
                        "<tr><td>教练您好，您正在注册健身私教预约系统，已查验你提交的注册材料，经过审核注册成功。</td></tr>" +
                        "<tr><td>欢迎进行登录，进行填写个人资料，就可以发布课程进行教学了。</td></tr>" +
                        "<tr><td>现在时间：" + DateUtil.getTime() + "</td></tr>" +
                        "</table></body></html>", true);
            } else {
                //文本
                mimeMessageHelper.setText("<!DOCTYPE html><html><head><meta charset='utf-8'><title></title></head><body>" +
                        "<table>" +
                        "<tr><th>欢迎注册健身私教预约系统</th></tr>" +
                        "<tr><td>教练您好，您正在注册健身私教预约系统，已查验你提交的注册材料，经过审核注册失败，请补充认证材料。</td></tr>" +
                        "<tr><td>失败的原因是：" + msg + "</td></tr>" +
                        "<tr><td>你可以直接回复邮箱补充材料，然后我们会再次审核，通过后会发送邮件通知您。</td></tr>" +
                        "<tr><td>现在时间：" + DateUtil.getTime() + "</td></tr>" +
                        "</table></body></html>", true);
            }
            mailSender.send(mimeMessage);
            log.info("发送邮件成功：发件人：{},收件人：{},主题：{},时间：{}", email, to, subject, DateUtil.getTime());
        } catch (MailSendException e) {
            Set<String> tmpInvalidMails = getInvalidAddress(e);
            // 非无效收件人导致的异常，暂不处理
            if (tmpInvalidMails.isEmpty()) {
                log.error(e.getMessage());
            }
            log.info("发送邮件失败：发件人：{},收件人：{},主题：{},时间：{},错误：{},结束：{}", email, to, subject, DateUtil.getTime(), e.getMessage(), "结束");
            return false;
        }
        return true;
    }

    private Set<String> getInvalidAddress(MailSendException e) {
        Set<String> mails = new HashSet<>();
        if (e != null) {
            for (Exception exception : e.getFailedMessages().values()) {
                if (exception != null && exception instanceof SendFailedException) {
                    SendFailedException sfe = (SendFailedException) exception;
                    Address[] invalidAddresses = sfe.getInvalidAddresses();
                    if (invalidAddresses != null) {
                        for (Address address : invalidAddresses) {
                            mails.add(address.toString());
                        }
                    }
                }
            }
        }
        return mails;
    }

}

